﻿#pragma once
#include "yzrutil.h"
#include "DSP.h"
#include "RingBuffer.h"
#include "array/Arrays.h"
#include "array/Array.hpp"

namespace yzrilyzr_dsp{
	ECLASS(BiquadIIR, public DSP){
	public:
	yzrilyzr_array::DoubleArray aCoeff;
	yzrilyzr_array::DoubleArray bCoeff;
	RingBufferSample input;
	RingBufferSample output;
	u_sample q=1;
	u_freq freq=1000;
	u_sample gain=0;
	int type=0;
	BiquadIIR() : aCoeff(2), bCoeff(3), input(3), output(2){
		static u_sample q_min=0.01;
		static u_sample q_max=10;
		static u_sample gain_min=-50;
		static u_sample gain_max=50;
		static const char * type_to_name[9]={"LOWPASS", "HIGHPASS", "BANDPASS", "BANDSTOP", "NOTCH", "LOWSHELF", "HIGHSHELF", "BELL", "ALLPASS"};
		registerParamFreq("Freq", &freq);
		registerParam("Q", yzrilyzr_util::ParamType::Sample, &q, &q_min, &q_max);
		registerParam("Gain", yzrilyzr_util::ParamType::Sample, &gain, &gain_min, &gain_max);
		registerParamEnum("Type", &type, type_to_name, 9);
	}
	BiquadIIR(yzrilyzr_array::DoubleArray & aClone, yzrilyzr_array::DoubleArray & bClone) : aCoeff(2), bCoeff(3), input(3), output(2){
		bCoeff[0]=bClone[0];
		bCoeff[1]=bClone[1];
		bCoeff[2]=bClone[2];
		aCoeff[0]=aClone[0];
		aCoeff[1]=aClone[1];
	}
	u_sample procDsp(u_sample v)override{
		input.write(v);
		u_sample y=0;
		y+=bCoeff[0] * (input.getFromNewest(0));
		y+=bCoeff[1] * (input.getFromNewest(1));
		y+=bCoeff[2] * (input.getFromNewest(2));
		y-=aCoeff[0] * (output.getFromNewest(0));
		y-=aCoeff[1] * (output.getFromNewest(1));
		output.write(y);
		return y;
	}
	void init(u_sample_rate sampleRate)override;
	void resetMemory()override{
		input.fill(0);
		output.fill(0);
	}
	std::shared_ptr<DSP> cloneDSP()override{
		return std::make_shared<BiquadIIR>(aCoeff, bCoeff);
	}
	void cloneParam(DSP * obj1)override{
		if(auto other=dynamic_cast<BiquadIIR *>(obj1)){
			freq=other->freq;
			q=other->q;
			gain=other->gain;
			type=other->type;
			bCoeff[0]=other->bCoeff[0];
			bCoeff[1]=other->bCoeff[1];
			bCoeff[2]=other->bCoeff[2];
			aCoeff[0]=other->aCoeff[0];
			aCoeff[1]=other->aCoeff[1];
		}
	}
	yzrilyzr_lang::String toString()const override;
	};
}